package web

import (
	"encoding/json"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"sync"
	"time"
)

// ConfigData 表示配置页面需要的数据
type ConfigData struct {
	Config       *Config
	IPv4Services []string
	IPv6Services []string
	SaveSuccess  bool
	ErrorMessage string
}

// Config 表示web配置接口使用的配置
type Config struct {
	CloudflareAPIToken string   `json:"cloudflare_api_token"`
	DomainNames        []string `json:"domain_names"`
	CheckInterval      int      `json:"check_interval"`
	IPVersion          string   `json:"ip_version"`
	IPv4Services       []string `json:"ipv4_services,omitempty"`
	IPv6Services       []string `json:"ipv6_services,omitempty"`
}

var (
	configLock     sync.Mutex
	configFilePath string
	webConfig      *Config
)

// 默认IPv4服务列表
var defaultIPv4Services = []string{
	"https://api.ipify.org",
	"https://ifconfig.me/ip",
	"https://icanhazip.com",
	"https://ipinfo.io/ip",
}

// 默认IPv6服务列表
var defaultIPv6Services = []string{
	"https://api6.ipify.org",
	"https://ifconfig.co/ip",
	"https://ipv6.icanhazip.com",
	"https://v6.ident.me",
	"http://v6.66666.host:66/ip",
	"https://ipv6.lookup.test-ipv6.com/ip/",
	"https://ipv6.whatismyip.com",
	"https://bot.whatismyipaddress.com",
}

// 加载配置文件
func loadConfig(filename string) (*Config, error) {
	configLock.Lock()
	defer configLock.Unlock()
	
	configFilePath = filename
	
	file, err := os.Open(filename)
	if err != nil {
		if os.IsNotExist(err) {
			// 如果配置文件不存在，创建一个默认配置
			webConfig = &Config{
				CloudflareAPIToken: "",
				DomainNames:        []string{""},
				CheckInterval:      300,
				IPVersion:          "ipv4",
				IPv4Services:       defaultIPv4Services,
				IPv6Services:       defaultIPv6Services,
			}
			return webConfig, nil
		}
		return nil, err
	}
	defer file.Close()

	config := &Config{}
	decoder := json.NewDecoder(file)
	err = decoder.Decode(config)
	if err != nil {
		return nil, err
	}
	
	// 如果配置中没有IP服务列表，使用默认值
	if len(config.IPv4Services) == 0 {
		config.IPv4Services = defaultIPv4Services
	}
	if len(config.IPv6Services) == 0 {
		config.IPv6Services = defaultIPv6Services
	}
	
	webConfig = config
	return config, nil
}

// 保存配置文件
func saveConfig(config *Config) error {
	configLock.Lock()
	defer configLock.Unlock()
	
	// 创建临时文件
	dir := filepath.Dir(configFilePath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return err
	}
	
	tempFile, err := os.CreateTemp(dir, "config-*.json")
	if err != nil {
		return err
	}
	tempFileName := tempFile.Name()
	
	// 写入配置数据
	encoder := json.NewEncoder(tempFile)
	encoder.SetIndent("", "  ")
	if err := encoder.Encode(config); err != nil {
		tempFile.Close()
		os.Remove(tempFileName)
		return err
	}
	
	// 关闭临时文件
	if err := tempFile.Close(); err != nil {
		os.Remove(tempFileName)
		return err
	}
	
	// 重命名临时文件
	if err := os.Rename(tempFileName, configFilePath); err != nil {
		os.Remove(tempFileName)
		return err
	}
	
	webConfig = config
	return nil
}

// API路由处理器 - 获取DDNS配置
func apiGetDDNSConfigHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	
	response := struct {
		Success bool   `json:"success"`
		Message string `json:"message,omitempty"`
		Data    *Config `json:"data,omitempty"`
	}{
		Success: true,
		Data:    webConfig,
	}
	
	json.NewEncoder(w).Encode(response)
}

// API路由处理器 - 更新DDNS配置
func apiUpdateDDNSConfigHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	
	// 读取请求体
	body, err := io.ReadAll(r.Body)
	if err != nil {
		errorResponse(w, "读取请求数据失败: "+err.Error(), http.StatusBadRequest)
		return
	}
	
	// 解析JSON
	var newConfig Config
	if err := json.Unmarshal(body, &newConfig); err != nil {
		errorResponse(w, "解析JSON数据失败: "+err.Error(), http.StatusBadRequest)
		return
	}
	
	// 验证配置数据
	if len(newConfig.DomainNames) == 0 {
		errorResponse(w, "至少需要一个域名", http.StatusBadRequest)
		return
	}
	
	if newConfig.CheckInterval < 60 {
		newConfig.CheckInterval = 60 // 最小60秒
	}
	
	// 确保IPv4/IPv6服务不为空
	if len(newConfig.IPv4Services) == 0 {
		newConfig.IPv4Services = defaultIPv4Services
	}
	
	if len(newConfig.IPv6Services) == 0 {
		newConfig.IPv6Services = defaultIPv6Services
	}
	
	// 保存配置
	if err := saveConfig(&newConfig); err != nil {
		errorResponse(w, "保存配置失败: "+err.Error(), http.StatusInternalServerError)
		return
	}
	
	// 返回成功
	successResponse(w, "配置已成功保存")
}

// 助手函数 - 发送错误响应
func errorResponse(w http.ResponseWriter, message string, statusCode int) {
	w.WriteHeader(statusCode)
	response := struct {
		Success bool   `json:"success"`
		Message string `json:"message"`
	}{
		Success: false,
		Message: message,
	}
	json.NewEncoder(w).Encode(response)
}

// 助手函数 - 发送成功响应
func successResponse(w http.ResponseWriter, message string) {
	response := struct {
		Success bool   `json:"success"`
		Message string `json:"message"`
	}{
		Success: true,
		Message: message,
	}
	json.NewEncoder(w).Encode(response)
}

// 前端文件处理器
func frontendHandler(w http.ResponseWriter, r *http.Request) {
	// 如果请求的是根路径，则提供index.html
	if r.URL.Path == "/" {
		http.ServeFile(w, r, "web/frontend/dist/index.html")
		return
	}
	
	// 提供静态文件
	path := "web/frontend/dist" + r.URL.Path
	
	// 检查文件是否存在
	_, err := os.Stat(path)
	if os.IsNotExist(err) {
		// 如果文件不存在，则提供index.html（用于SPA路由）
		http.ServeFile(w, r, "web/frontend/dist/index.html")
		return
	}
	
	// 提供静态文件
	http.ServeFile(w, r, path)
}

// 导入日志类型
type DDNSLogEntry struct {
	Timestamp    time.Time `json:"timestamp"`    // 日志时间
	IPVersion    string    `json:"ip_version"`   // IP版本（IPv4/IPv6）
	CurrentIP    string    `json:"current_ip"`   // 当前检测到的IP
	PreviousIP   string    `json:"previous_ip"`  // 上一次的IP
	Changed      bool      `json:"changed"`      // IP是否变化
	Domains      []string  `json:"domains"`      // 更新的域名列表
	Success      bool      `json:"success"`      // 更新是否成功
	ErrorMessage string    `json:"error_message"`// 错误信息（如果有）
}

// 获取日志的函数类型
type GetLogsFunc func(count int) []DDNSLogEntry

// 获取日志回调函数
var getLogsCallback GetLogsFunc

// 设置获取日志的回调函数
func SetGetLogsCallback(callback GetLogsFunc) {
	getLogsCallback = callback
}

// API路由处理器 - 获取日志
func apiGetLogsHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	
	// 如果回调函数未设置，返回空数组
	if getLogsCallback == nil {
		json.NewEncoder(w).Encode([]DDNSLogEntry{})
		return
	}
	
	// 获取查询参数
	count := 20 // 默认获取20条日志
	countParam := r.URL.Query().Get("count")
	if countParam != "" {
		var err error
		count, err = strconv.Atoi(countParam)
		if err != nil || count <= 0 {
			count = 20
		}
	}
	
	// 获取日志数据
	logs := getLogsCallback(count)
	
	// 返回JSON
	response := struct {
		Success bool          `json:"success"`
		Data    []DDNSLogEntry `json:"data"`
	}{
		Success: true,
		Data:    logs,
	}
	
	json.NewEncoder(w).Encode(response)
}

// 启动Web服务器
func StartWebServer(configFile string, reloadFunc func()) error {
	// 加载配置
	_, err := loadConfig(configFile)
	if err != nil {
		return err
	}
	
	// 创建CORS中间件
	corsMiddleware := func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Access-Control-Allow-Origin", "*")
			w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
			w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
			
			if r.Method == "OPTIONS" {
				w.WriteHeader(http.StatusOK)
				return
			}
			
			next.ServeHTTP(w, r)
		})
	}
	
	// 创建路由
	mux := http.NewServeMux()
	
	// DDNS API路由
	mux.HandleFunc("/api/ddns/config", func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case http.MethodGet:
			apiGetDDNSConfigHandler(w, r)
		case http.MethodPost:
			apiUpdateDDNSConfigHandler(w, r)
			// 配置更新后，延迟1秒调用重新加载函数
			if reloadFunc != nil {
				go func() {
					time.Sleep(1 * time.Second)
					reloadFunc()
				}()
			}
		default:
			http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
		}
	})
	
	// 添加日志API路由
	mux.HandleFunc("/api/logs", apiGetLogsHandler)
	
	// 注册文件服务器API路由
	RegisterFileServerAPIRoutes(mux)
	
	// 前端路由
	mux.HandleFunc("/", frontendHandler)
	
	// 应用CORS中间件
	handler := corsMiddleware(mux)
	
	log.Println("Web配置界面已启动，请访问: http://localhost:8080")
	return http.ListenAndServe(":8080", handler)
}

// 获取Web配置
func GetWebConfig() *Config {
	return webConfig
} 